home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume24 / mkid2 / part06 < prev    next >
Encoding:
Internet Message Format  |  1991-10-09  |  22.8 KB

  1. Subject:  v24i094:  Program identifier database tools, Part06/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: cd18a1dc d6f71fde ad02f061 9637390e
  5.  
  6. Submitted-by: Tom Horsley <tom@hcx2.ssd.csd.harris.com>
  7. Posting-number: Volume 24, Issue 94
  8. Archive-name: mkid2/part06
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 6 (of 7)."
  17. # Contents:  lid.c
  18. # Wrapped by tom@hcx2 on Tue Feb 26 10:03:07 1991
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. if test -f 'lid.c' -a "${1}" != "-c" ; then 
  21.   echo shar: Will not clobber existing file \"'lid.c'\"
  22. else
  23. echo shar: Extracting \"'lid.c'\" \(20773 characters\)
  24. sed "s/^X//" >'lid.c' <<'END_OF_FILE'
  25. Xstatic char copyright[] = "@(#)Copyright (c) 1986, Greg McGary";
  26. Xstatic char sccsid[] = "@(#)lid.c    1.4 86/11/06";
  27. X
  28. X#include    <bool.h>
  29. X#include    <stdio.h>
  30. X#include    <string.h>
  31. X#include    <ctype.h>
  32. X#include    <signal.h>
  33. X#include    <errno.h>
  34. X#include    <radix.h>
  35. X#include    <id.h>
  36. X#include    <bitops.h>
  37. X#include    <extern.h>
  38. X
  39. X#ifdef REGEX
  40. Xextern char *regex();
  41. Xextern char *regcmp();
  42. X#endif
  43. X#ifdef RE_EXEC
  44. Xextern char *re_comp();
  45. Xextern int re_exec();
  46. X#endif
  47. X
  48. Xbool isMagic();
  49. Xchar **bitsToArgv();
  50. Xchar *fileRE();
  51. Xchar *strcpos();
  52. Xint skipToArgv();
  53. Xint findAnchor();
  54. Xint findApropos();
  55. X#if REGEX || RE_EXEC
  56. Xint findRegExp();
  57. X#endif
  58. Xint matchPaths();
  59. Xint findNonUnique();
  60. Xint findNumber();
  61. Xint findPlain();
  62. Xint idCompare();
  63. Xlong searchName();
  64. Xvoid editId();
  65. Xvoid grepId();
  66. Xvoid lookId();
  67. X
  68. X#ifdef USG
  69. X#define    TOLOWER(c)    (isupper(c) ? _tolower(c) : (c))
  70. X#else
  71. X#define    TOLOWER(c)    (isupper(c) ? tolower(c) : (c))
  72. X#endif
  73. X
  74. X#ifndef CRUNCH_DEFAULT
  75. X#define CRUNCH_DEFAULT TRUE
  76. X#endif
  77. X
  78. X/*
  79. X*  Sorry about all the globals, but it's really cleaner this way.
  80. X*/
  81. XFILE        *IdFILE;
  82. Xbool        Merging;
  83. Xbool        Radix;
  84. Xbool            EchoOn = TRUE;
  85. Xbool            CrunchOn = CRUNCH_DEFAULT;
  86. Xbool        pathRegExp = FALSE;
  87. Xbool        matchBase = FALSE;
  88. Xchar        IdDir[BUFSIZ];
  89. Xlong        AnchorOffset;
  90. Xint        BitArraySize;
  91. Xchar        PWDname[BUFSIZ];
  92. Xstruct idhead    Idh;
  93. Xstruct idarg    *IdArgs;
  94. Xint        (*FindFunc)() = NULL;
  95. Xint        Solo = 0;
  96. X#define    IGNORE_SOLO(buf) \
  97. X( \
  98. X       (Solo == '-' && !(ID_FLAGS(buf) & IDN_SOLO)) \
  99. X    || (Solo == '+' &&  (ID_FLAGS(buf) & IDN_SOLO)) \
  100. X)
  101. X
  102. Xchar *MyName;
  103. Xstatic void
  104. Xusage()
  105. X{
  106. X    fprintf(stderr, "Usage: %s [-f<file>] [-u<n>] [-r<dir>] [-mewdoxasknc] patterns...\n", MyName);
  107. X    exit(1);
  108. X}
  109. Xmain(argc, argv)
  110. X    int        argc;
  111. X    char        **argv;
  112. X{
  113. X    char        *idFile = IDFILE;
  114. X    char        *arg;
  115. X    long        val;
  116. X    void        (*doit)();
  117. X    bool        forceMerge = FALSE;
  118. X    int        uniqueLimit = 0;
  119. X    int        useIDpath = TRUE;
  120. X    int        usePWDpath = FALSE;
  121. X    int        useRELpath = FALSE;
  122. X    char *        RELpath;
  123. X    int        op;
  124. X
  125. X    MyName = basename(GETARG(argc, argv));
  126. X
  127. X    while (argc) {
  128. X        arg = GETARG(argc, argv);
  129. X        switch (op = *arg++)
  130. X        {
  131. X        case '-':
  132. X        case '+':
  133. X            break;
  134. X        default:
  135. X            UNGETARG(argc, argv);
  136. X            goto argsdone;
  137. X        }
  138. X        while (*arg) switch (*arg++)
  139. X        {
  140. X        case 'f': idFile = arg; goto nextarg;
  141. X        case 'u': uniqueLimit = stoi(arg); goto nextarg;
  142. X        case 'm': forceMerge = TRUE; break;
  143. X#if REGEX || RE_EXEC
  144. X        case 'e': FindFunc = findRegExp; pathRegExp = TRUE; break;
  145. X#endif
  146. X        case 'w': FindFunc = findPlain; break;
  147. X        case 'd': Radix |= RADIX_DEC; break;
  148. X        case 'o': Radix |= RADIX_OCT; break;
  149. X        case 'x': Radix |= RADIX_HEX; break;
  150. X        case 'a': Radix |= RADIX_ALL; break;
  151. X        case 's': Solo = op; break;
  152. X        case 'k': CrunchOn = FALSE; break;
  153. X        case 'g': CrunchOn = TRUE; break;
  154. X        case 'n': EchoOn = FALSE; break;
  155. X        case 'c': useIDpath = FALSE; usePWDpath = TRUE; break;
  156. X        case 'b': matchBase = TRUE; break;
  157. X        case 'r': useIDpath = FALSE; useRELpath = TRUE;
  158. X            RELpath = arg; goto nextarg;
  159. X        default:
  160. X            usage();
  161. X        }
  162. X    nextarg:;
  163. X    }
  164. Xargsdone:
  165. X
  166. X    if (usePWDpath && useRELpath) {
  167. X        fprintf(stderr,"%s: please use only one of -c or -r\n",MyName);
  168. X        usage();
  169. X    }
  170. X    /* Look for the ID database up the tree */
  171. X    if ((idFile = LookUp(idFile)) == NULL) {
  172. X        filerr("open", idFile);
  173. X        exit(1);
  174. X    }
  175. X    /* Find out current directory to relate names to */
  176. X    if (kshgetwd(PWDname) == NULL) {
  177. X        fprintf(stderr,"%s: cannot determine current directory\n",MyName);
  178. X        exit(1);
  179. X    }
  180. X    strcat(PWDname,"/");
  181. X    /* Determine absolute path name that database files are relative to */
  182. X    if (useIDpath) {
  183. X        strcpy(IdDir, spanPath(PWDname, idFile));
  184. X        *(strrchr(IdDir, '/') + 1) = '\0';
  185. X    } else if (usePWDpath) {
  186. X        strcpy(IdDir, PWDname);
  187. X    } else {
  188. X        strcpy(IdDir, spanPath(PWDname, RELpath));
  189. X        strcat(IdDir, "/");
  190. X    }
  191. X    if ((IdFILE = initID(idFile, &Idh, &IdArgs)) == NULL) {
  192. X        filerr("open", idFile);
  193. X        exit(1);
  194. X    }
  195. X    BitArraySize = (Idh.idh_pthc + 7) >> 3;
  196. X
  197. X    switch (MyName[0])
  198. X    {
  199. X    case 'a':
  200. X        FindFunc = findApropos;
  201. X        /*FALLTHROUGH*/
  202. X    case 'l':
  203. X        doit = lookId;
  204. X        break;
  205. X    case 'g':
  206. X        doit = grepId;
  207. X        break;
  208. X    case 'e':
  209. X        doit = editId;
  210. X        break;
  211. X    case 'p':
  212. X        FindFunc = matchPaths;
  213. X        doit = lookId;
  214. X        break;
  215. X    default:
  216. X        MyName = "[algep]id";
  217. X        usage();
  218. X    }
  219. X
  220. X    if (argc == 0) {
  221. X        UNGETARG(argc, argv);
  222. X        *argv = ".";
  223. X    }
  224. X
  225. X    while (argc) {
  226. X        arg = GETARG(argc, argv);
  227. X        if (FindFunc)
  228. X            ;
  229. X        else if ((radix(arg)) && (val = stoi(arg)) >= 0)
  230. X            FindFunc = findNumber;
  231. X#if REGEX || RE_EXEC
  232. X        else if (isMagic(arg))
  233. X            FindFunc = findRegExp;
  234. X#endif
  235. X        else if (arg[0] == '^')
  236. X            FindFunc = findAnchor;
  237. X        else
  238. X            FindFunc = findPlain;
  239. X
  240. X        if ((doit == lookId && !forceMerge)
  241. X        || (FindFunc == findNumber && bitCount(Radix) > 1 && val > 7))
  242. X            Merging = FALSE;
  243. X        else
  244. X            Merging = TRUE;
  245. X
  246. X        if (uniqueLimit) {
  247. X            if (!findNonUnique(uniqueLimit, doit))
  248. X                fprintf(stderr, "All identifiers are unique within the first %d characters\n", uniqueLimit);
  249. X            exit(0);
  250. X        } else if (!(*FindFunc)(arg, doit)) {
  251. X            fprintf(stderr, "%s: not found\n", arg);
  252. X            continue;
  253. X        }
  254. X    }
  255. X    exit(0);
  256. X}
  257. X
  258. Xvoid
  259. XlookId(name, argv)
  260. X    char        *name;
  261. X    register char    **argv;
  262. X{
  263. X    register char    *arg;
  264. X    register bool    crunching = FALSE;
  265. X    register char    *dir;
  266. X
  267. X    if (EchoOn) printf("%-14s ", name);
  268. X    while (*argv) {
  269. X        arg = *argv++;
  270. X        if (*argv && CrunchOn && canCrunch(arg, *argv)) {
  271. X            if (crunching)
  272. X                printf(",%s", rootName(arg));
  273. X            else if ((dir = dirname(arg)) && dir[0] == '.' && dir[1] == '\0')
  274. X                printf("{%s", rootName(arg));
  275. X            else
  276. X                printf("%s/{%s", dir, rootName(arg));
  277. X            /*}}*/
  278. X            crunching = TRUE;
  279. X        } else {
  280. X            if (crunching) /*{*/
  281. X                printf(",%s}%s", rootName(arg), suffName(arg));
  282. X            else
  283. X                fputs(arg, stdout);
  284. X            crunching = FALSE;
  285. X            if (*argv)
  286. X                putchar(' ');
  287. X        }
  288. X    }
  289. X    putchar('\n');
  290. X}
  291. X
  292. Xvoid
  293. XgrepId(name, argv)
  294. X    char        *name;
  295. X    char        **argv;
  296. X{
  297. X    FILE        *gidFILE;
  298. X    char        *gidName;
  299. X    char        buf[BUFSIZ];
  300. X    char        *delimit = "[^a-zA-Z0-9_]";
  301. X    char        *re;
  302. X    char        *reCompiled;
  303. X    int        lineNumber;
  304. X
  305. X    if (!Merging || (re = fileRE(name, delimit, delimit)) == NULL)
  306. X        re = NULL;
  307. X#ifdef REGEX
  308. X    else if ((reCompiled = regcmp(re, 0)) == NULL) {
  309. X        fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  310. X        return;
  311. X    }
  312. X#endif
  313. X#ifdef RE_EXEC
  314. X    else if ((reCompiled = re_comp(re)) != NULL) {
  315. X        fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  316. X        return;
  317. X    }
  318. X#endif
  319. X
  320. X    buf[0] = ' ';    /* sentry */
  321. X    while (*argv) {
  322. X        if ((gidFILE = fopen(gidName = *argv++, "r")) == NULL) {
  323. X            filerr("open", gidName);
  324. X            continue;
  325. X        }
  326. X        lineNumber = 0;
  327. X        while (fgets(&buf[1], sizeof(buf), gidFILE)) {
  328. X            lineNumber++;
  329. X            if (re) {
  330. X#ifdef REGEX
  331. X                if (regex(reCompiled, buf) == NULL)
  332. X#endif
  333. X#ifdef RE_EXEC
  334. X                if (!re_exec(buf))
  335. X#endif
  336. X                    continue;
  337. X            } else if (!wordMatch(name, buf))
  338. X                continue;
  339. X            printf("%s:%d: %s", gidName, lineNumber, &buf[1]);
  340. X        }
  341. X        fclose(gidFILE);
  342. X    }
  343. X}
  344. X
  345. Xvoid
  346. XeditId(name, argv)
  347. X    char        *name;
  348. X    char        **argv;
  349. X{
  350. X    char        reBuf[BUFSIZ];
  351. X    char        edArgBuf[BUFSIZ];
  352. X    char        *re;
  353. X    int        c;
  354. X    int        skip;
  355. X    static char    *editor, *eidArg, *eidRightDel, *eidLeftDel;
  356. X
  357. X    if (editor == NULL && (editor = getenv("EDITOR")) == NULL) {
  358. X        char    *ucb_vi = "/usr/ucb/vi";
  359. X        char    *bin_vi = "/usr/bin/vi";
  360. X
  361. X        if (access(ucb_vi, 01) == 0)
  362. X            editor = ucb_vi;
  363. X        else if (access(bin_vi, 01) == 0)
  364. X            editor = bin_vi;
  365. X        else
  366. X            editor = "/bin/ed";    /* YUCK! */
  367. X        if (editor == ucb_vi || editor == bin_vi) {
  368. X            eidArg = "+1;/%s/";
  369. X            eidLeftDel = "\\<";
  370. X            eidRightDel = "\\>";
  371. X        }
  372. X    }
  373. X    if (eidLeftDel == NULL) {
  374. X        eidArg = getenv("EIDARG");
  375. X        if ((eidLeftDel = getenv("EIDLDEL")) == NULL)
  376. X            eidLeftDel = "";
  377. X        if ((eidRightDel = getenv("EIDRDEL")) == NULL)
  378. X            eidRightDel = "";
  379. X    }
  380. X
  381. X    lookId(name, argv);
  382. X    savetty();
  383. X    for (;;) {
  384. X        printf("Edit? [y1-9^S/nq] "); fflush(stdout);
  385. X        chartty();
  386. X        c = (getchar() & 0177);
  387. X        restoretty();
  388. X        switch (TOLOWER(c))
  389. X        {
  390. X        case '/': case ('s'&037):
  391. X            putchar('/');
  392. X            /*FALLTHROUGH*/
  393. X            if ((skip = skipToArgv(argv)) < 0)
  394. X                continue;
  395. X            argv += skip;
  396. X            goto editit;
  397. X        case '1': case '2': case '3': case '4':
  398. X        case '5': case '6': case '7': case '8': case '9':
  399. X            putchar(c);
  400. X            skip = c - '0';
  401. X            break;
  402. X        case 'y':
  403. X            putchar(c);
  404. X            /*FALLTHROUGH*/
  405. X        case '\n':
  406. X        case '\r':
  407. X            skip = 0;
  408. X            break;
  409. X        case 'q':
  410. X            putchar(c);
  411. X            putchar('\n');
  412. X            exit(0);
  413. X        case 'n':
  414. X            putchar(c);
  415. X            putchar('\n');
  416. X            return;
  417. X        default:
  418. X            putchar(c);
  419. X            putchar('\n');
  420. X            continue;
  421. X        }
  422. X
  423. X        putchar('\n');
  424. X        while (skip--)
  425. X            if (*++argv == NULL)
  426. X                continue;
  427. X        break;
  428. X    }
  429. Xeditit:
  430. X
  431. X    if (!Merging || (re = fileRE(name, eidLeftDel, eidRightDel)) == NULL)
  432. X        sprintf(re = reBuf, "%s%s%s", eidLeftDel, name, eidRightDel);
  433. X
  434. X    switch (fork())
  435. X    {
  436. X    case -1:
  437. X        fprintf(stderr, "%s: Cannot fork (%s)\n", MyName, uerror());
  438. X        exit(1);
  439. X    case 0:
  440. X        argv--;
  441. X        if (eidArg) {
  442. X            argv--;
  443. X            sprintf(edArgBuf, eidArg, re);
  444. X            argv[1] = edArgBuf;
  445. X        }
  446. X        argv[0] = editor;
  447. X        execv(editor, argv);
  448. X        filerr("exec", editor);
  449. X    default:
  450. X        {
  451. X            int (*oldint)() = signal(SIGINT, SIG_IGN);
  452. X            int (*oldquit)() = signal(SIGQUIT, SIG_IGN);
  453. X
  454. X            while(wait(0) == -1 && errno == EINTR)
  455. X                /* loop */;
  456. X
  457. X            (void) signal(SIGINT, oldint);
  458. X            (void) signal(SIGQUIT, oldquit);
  459. X        }
  460. X        break;
  461. X    }
  462. X}
  463. X
  464. Xint
  465. XskipToArgv(argv)
  466. X    char        **argv;
  467. X{
  468. X    char        pattern[BUFSIZ];
  469. X    int        count;
  470. X
  471. X    if (gets(pattern) == NULL)
  472. X        return -1;
  473. X    
  474. X    for (count = 0; *argv; count++, argv++)
  475. X        if (strcpos(*argv, pattern))
  476. X            return count;
  477. X    return -1;
  478. X}
  479. X
  480. Xint
  481. XfindPlain(arg, doit)
  482. X    char        *arg;
  483. X    void        (*doit)();
  484. X{
  485. X    static char    *buf, *bitArray;
  486. X    int        size;
  487. X
  488. X    if (searchName(arg) == 0)
  489. X        return 0;
  490. X    if (buf == NULL) {
  491. X        buf = malloc(Idh.idh_bsiz);
  492. X        bitArray = malloc(BitArraySize);
  493. X    }
  494. X    bzero(bitArray, BitArraySize);
  495. X
  496. X    if ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) == 0)
  497. X        return 0;
  498. X    size++;
  499. X    getsFF(&buf[size], IdFILE);
  500. X    if (IGNORE_SOLO(buf))
  501. X        return 0;
  502. X
  503. X    vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  504. X    (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  505. X    return 1;
  506. X}
  507. X
  508. Xint
  509. XfindAnchor(arg, doit)
  510. X    register char    *arg;
  511. X    void        (*doit)();
  512. X{
  513. X    static char    *buf, *bitArray;
  514. X    int        count, size;
  515. X    int        len;
  516. X
  517. X    if (searchName(++arg) == 0)
  518. X        return 0;
  519. X
  520. X    if (buf == NULL) {
  521. X        buf = malloc(Idh.idh_bsiz);
  522. X        bitArray = malloc(BitArraySize);
  523. X    }
  524. X    bzero(bitArray, BitArraySize);
  525. X
  526. X    len = strlen(arg);
  527. X    count = 0;
  528. X    while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  529. X        size++;
  530. X        getsFF(&buf[size], IdFILE);
  531. X        if (IGNORE_SOLO(buf))
  532. X            continue;
  533. X        if (!strnequ(arg, ID_STRING(buf), len))
  534. X            break;
  535. X        vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  536. X        if (!Merging) {
  537. X            (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  538. X            bzero(bitArray, BitArraySize);
  539. X        }
  540. X        count++;
  541. X    }
  542. X    if (Merging && count)
  543. X        (*doit)(--arg, bitsToArgv(bitArray));
  544. X
  545. X    return count;
  546. X}
  547. X
  548. X#if REGEX || RE_EXEC
  549. Xint
  550. XfindRegExp(re, doit)
  551. X    char        *re;
  552. X    void        (*doit)();
  553. X{
  554. X    static char    *buf, *bitArray;
  555. X    int        count, size;
  556. X    char        *reCompiled;
  557. X
  558. X#ifdef REGEX
  559. X    if ((reCompiled = regcmp(re, 0)) == NULL) {
  560. X        fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  561. X        return 0;
  562. X    }
  563. X#endif
  564. X#ifdef RE_EXEC
  565. X    if ((reCompiled = re_comp(re)) != NULL) {
  566. X        fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  567. X        return 0;
  568. X    }
  569. X#endif
  570. X    fseek(IdFILE, Idh.idh_namo, 0);
  571. X
  572. X    if (buf == NULL) {
  573. X        buf = malloc(Idh.idh_bsiz);
  574. X        bitArray = malloc(BitArraySize);
  575. X    }
  576. X    bzero(bitArray, BitArraySize);
  577. X
  578. X    count = 0;
  579. X    while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  580. X        size++;
  581. X        getsFF(&buf[size], IdFILE);
  582. X        if (IGNORE_SOLO(buf))
  583. X            continue;
  584. X#ifdef REGEX
  585. X        if (regex(reCompiled, ID_STRING(buf)) == NULL)
  586. X#endif
  587. X#ifdef RE_EXEC
  588. X        if (!re_exec(ID_STRING(buf)))
  589. X#endif
  590. X            continue;
  591. X        vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  592. X        if (!Merging) {
  593. X            (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  594. X            bzero(bitArray, BitArraySize);
  595. X        }
  596. X        count++;
  597. X    }
  598. X    if (Merging && count)
  599. X        (*doit)(re, bitsToArgv(bitArray));
  600. X
  601. X    return count;
  602. X}
  603. X#endif
  604. X
  605. Xint
  606. XfindNumber(arg, doit)
  607. X    char        *arg;
  608. X    void        (*doit)();
  609. X{
  610. X    static char    *buf, *bitArray;
  611. X    int        count, size;
  612. X    register int    rdx = 0;
  613. X    register int    val;
  614. X    register bool    hitDigits = FALSE;
  615. X
  616. X    if ((val = stoi(arg)) <= 7)
  617. X        rdx |= RADIX_ALL;
  618. X    else
  619. X        rdx = radix(arg);
  620. X    fseek(IdFILE, Idh.idh_namo, 0);
  621. X
  622. X    if (buf == NULL) {
  623. X        buf = malloc(Idh.idh_bsiz);
  624. X        bitArray = malloc(BitArraySize);
  625. X    }
  626. X    bzero(bitArray, BitArraySize);
  627. X
  628. X    count = 0;
  629. X    while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  630. X        size++;
  631. X        getsFF(&buf[size], IdFILE);
  632. X        if (hitDigits) {
  633. X            if (!isdigit(*ID_STRING(buf)))
  634. X                break;
  635. X        } else if (isdigit(*ID_STRING(buf)))
  636. X            hitDigits = TRUE;
  637. X
  638. X        if (!((Radix ? Radix : rdx) & radix(ID_STRING(buf)))
  639. X        || stoi(ID_STRING(buf)) != val)
  640. X            continue;
  641. X        vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  642. X        if (!Merging) {
  643. X            (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  644. X            bzero(bitArray, BitArraySize);
  645. X        }
  646. X        count++;
  647. X    }
  648. X    if (Merging && count)
  649. X        (*doit)(arg, bitsToArgv(bitArray));
  650. X
  651. X    return count;
  652. X}
  653. X
  654. X/*
  655. X    Find identifiers that are non-unique within
  656. X    the first `count' characters.
  657. X*/
  658. Xint
  659. XfindNonUnique(limit, doit)
  660. X    int        limit;
  661. X    void        (*doit)();
  662. X{
  663. X    static char    *buf1, *buf2, *bitArray;
  664. X    register char    *old;
  665. X    register char    *new;
  666. X    register int    consecutive;
  667. X    char        *cptmp;
  668. X    int        itmp;
  669. X    int        count, oldsize, newsize;
  670. X    char        *name;
  671. X
  672. X    if (limit <= 1)
  673. X        usage();
  674. X
  675. X    fseek(IdFILE, Idh.idh_namo, 0);
  676. X
  677. X    if (buf1 == NULL) {
  678. X        buf1 = malloc(Idh.idh_bsiz);
  679. X        buf2 = malloc(Idh.idh_bsiz);
  680. X        bitArray = malloc(BitArraySize);
  681. X    }
  682. X    bzero(bitArray, BitArraySize);
  683. X
  684. X    name = calloc(1, limit+2);
  685. X    name[0] = '^';
  686. X    old = buf1;
  687. X    *ID_STRING(new = buf2) = '\0';
  688. X    count = consecutive = 0;
  689. X    while ((oldsize = fgets0(old, Idh.idh_bsiz, IdFILE)) > 0) {
  690. X        oldsize++;
  691. X        getsFF(&old[oldsize], IdFILE);
  692. X        if (!(ID_FLAGS(old) & IDN_NAME))
  693. X            continue;
  694. X        cptmp = old; old = new; new = cptmp;
  695. X        itmp = oldsize; oldsize = newsize; newsize = itmp;
  696. X        if (!strnequ(ID_STRING(new), ID_STRING(old), limit)) {
  697. X            if (consecutive && Merging) {
  698. X                strncpy(&name[1], ID_STRING(old), limit); 
  699. X                (*doit)(name, bitsToArgv(bitArray));
  700. X            }
  701. X            consecutive = 0;
  702. X            continue;
  703. X        }
  704. X        if (!consecutive++) {
  705. X            vecToBits(bitArray, &old[oldsize], Idh.idh_vecc);
  706. X            if (!Merging) {
  707. X                (*doit)(ID_STRING(old), bitsToArgv(bitArray));
  708. X                bzero(bitArray, BitArraySize);
  709. X            }
  710. X            count++;
  711. X        }
  712. X        vecToBits(bitArray, &new[newsize], Idh.idh_vecc);
  713. X        if (!Merging) {
  714. X            (*doit)(ID_STRING(new), bitsToArgv(bitArray));
  715. X            bzero(bitArray, BitArraySize);
  716. X        }
  717. X        count++;
  718. X    }
  719. X
  720. X    return count;
  721. X}
  722. X
  723. Xint
  724. XfindApropos(arg, doit)
  725. X    char        *arg;
  726. X    void        (*doit)();
  727. X{
  728. X    static char    *buf, *bitArray;
  729. X    int        count, size;
  730. X
  731. X    fseek(IdFILE, Idh.idh_namo, 0);
  732. X
  733. X    if (buf == NULL) {
  734. X        buf = malloc(Idh.idh_bsiz);
  735. X        bitArray = malloc(BitArraySize);
  736. X    }
  737. X    bzero(bitArray, BitArraySize);
  738. X
  739. X    count = 0;
  740. X    while ((size = fgets0(buf, Idh.idh_bsiz, IdFILE)) > 0) {
  741. X        size++;
  742. X        getsFF(&buf[size], IdFILE);
  743. X        if (IGNORE_SOLO(buf))
  744. X            continue;
  745. X        if (strcpos(ID_STRING(buf), arg) == NULL)
  746. X            continue;
  747. X        vecToBits(bitArray, &buf[size], Idh.idh_vecc);
  748. X        if (!Merging) {
  749. X            (*doit)(ID_STRING(buf), bitsToArgv(bitArray));
  750. X            bzero(bitArray, BitArraySize);
  751. X        }
  752. X        count++;
  753. X    }
  754. X    if (Merging && count)
  755. X        (*doit)(arg, bitsToArgv(bitArray));
  756. X
  757. X    return count;
  758. X}
  759. X
  760. X/*
  761. X    if string `s2' occurs in `s1', return a pointer to the
  762. X    first match.  Ignore differences in alphabetic case.
  763. X*/
  764. Xchar *
  765. Xstrcpos(s1, s2)
  766. X    char        *s1;
  767. X    char        *s2;
  768. X{
  769. X    register char    *s1p;
  770. X    register char    *s2p;
  771. X    char        *s1last;
  772. X
  773. X    for (s1last = &s1[strlen(s1) - strlen(s2)]; s1 <= s1last; s1++)
  774. X        for (s1p = s1, s2p = s2; TOLOWER(*s1p) == TOLOWER(*s2p); s1p++)
  775. X            if (*++s2p == '\0')
  776. X                return s1;
  777. X    return NULL;
  778. X}
  779. X
  780. X/*
  781. X    Convert the regular expression that we used to
  782. X    locate identifiers in the id database into one
  783. X    suitable for locating the identifiers in files.
  784. X*/
  785. Xchar *
  786. XfileRE(name0, leftDelimit, rightDelimit)
  787. X    char        *name0;
  788. X    char        *leftDelimit;
  789. X    char        *rightDelimit;
  790. X{
  791. X    static char    reBuf[BUFSIZ];
  792. X    register char    *name = name0;
  793. X
  794. X    if (FindFunc == findNumber && Merging) {
  795. X        sprintf(reBuf, "%s0*[Xx]*0*%d[Ll]*%s", leftDelimit, stoi(name), rightDelimit);
  796. X        return reBuf;
  797. X    }
  798. X
  799. X    if (!isMagic(name) && name[0] != '^')
  800. X        return NULL;
  801. X
  802. X    if (name[0] == '^')
  803. X        name0++;
  804. X    else
  805. X        leftDelimit = "";
  806. X    while (*++name)
  807. X        ;
  808. X    if (*--name == '$')
  809. X        *name = '\0';
  810. X    else
  811. X        rightDelimit = "";
  812. X
  813. X    sprintf(reBuf, "%s%s%s", leftDelimit, name0, rightDelimit);
  814. X    return reBuf;
  815. X}
  816. X
  817. Xlong
  818. XsearchName(name)
  819. X    char        *name;
  820. X{
  821. X    long        offset;
  822. X
  823. X    AnchorOffset = 0;
  824. X    offset = (long)bsearch(name, (char *)(Idh.idh_namo-1), Idh.idh_endo-(Idh.idh_namo-1), 1, idCompare);
  825. X    if (offset == 0)
  826. X        offset = AnchorOffset;
  827. X    if (offset == 0)
  828. X        return 0;
  829. X    fseek(IdFILE, offset, 0);
  830. X    skipFF(IdFILE);
  831. X    return ftell(IdFILE);
  832. X}
  833. X
  834. Xint
  835. XidCompare(key, offset)
  836. X    register char    *key;
  837. X    long        offset;
  838. X{
  839. X    register int    c;
  840. X
  841. X    fseek(IdFILE, offset, 0);
  842. X    skipFF(IdFILE);
  843. X    getc(IdFILE);
  844. X
  845. X    while (*key == (c = getc(IdFILE)))
  846. X        if (*key++ == '\0')
  847. X            return 0;
  848. X    if (*key == '\0' && FindFunc == findAnchor)
  849. X        AnchorOffset = offset;
  850. X
  851. X    return *key - c;
  852. X}
  853. X
  854. X/*
  855. X    Are there any magic Regular Expression meta-characters in name??
  856. X*/
  857. Xbool
  858. XisMagic(name)
  859. X    register char    *name;
  860. X{
  861. X    char        *magichar = "[]{}().*+^$";
  862. X    int        backslash = 0;
  863. X
  864. X    if (*name == '^')
  865. X        name++;
  866. X    while (*name) {
  867. X        if (*name == '\\')
  868. X            name++, backslash++;
  869. X        else if (strchr(magichar, *name))
  870. X            return TRUE;
  871. X        name++;
  872. X    }
  873. X    if (backslash)
  874. X        while (*name) {
  875. X            if (*name == '\\')
  876. X                strcpy(name, name+1);
  877. X            name++;
  878. X        }
  879. X    return FALSE;
  880. X}
  881. X
  882. Xchar **
  883. XbitsToArgv(bitArray)
  884. X    char        *bitArray;
  885. X{
  886. X    char *        absname;
  887. X    char *        relname;
  888. X    static char    **argv;
  889. X    struct idarg    *idArgs;
  890. X    register char    **av;
  891. X    register int    i;
  892. X#define    ARGV1stPATH    3 /* available argv[] slots before first pathname */
  893. X
  894. X    if (argv == NULL)
  895. X        argv = (char **)malloc(sizeof(char *) * (Idh.idh_pthc + ARGV1stPATH + 2));
  896. X
  897. X    av = argv + ARGV1stPATH;
  898. X    for (idArgs = IdArgs, i = 0; i < Idh.idh_pthc; i++, idArgs++) {
  899. X        if (!BITTST(bitArray, i))
  900. X            continue;
  901. X        if (idArgs->ida_flags & IDA_BLANK) {
  902. X            continue;
  903. X        }
  904. X        if (!(idArgs->ida_flags & IDA_ADJUST)) {
  905. X            absname = spanPath(IdDir, idArgs->ida_arg);
  906. X            relname = relPath(PWDname, absname);
  907. X            idArgs->ida_arg = strsav(strlen(relname) > strlen(absname) ? absname : relname);
  908. X            idArgs->ida_flags |= IDA_ADJUST;
  909. X        }
  910. X        *av++ = idArgs->ida_arg;
  911. X    }
  912. X    *av = NULL;
  913. X    return (argv + ARGV1stPATH);
  914. X}
  915. X
  916. X/* pathWildCard implements a simple pattern matcher that emulates the
  917. X * shell wild card capability.
  918. X *
  919. X *   * - any string of chars
  920. X *   ? - any char
  921. X *   [] - any char in set (if first char is !, any not in set)
  922. X *   \ - literal match next char
  923. X */
  924. Xint
  925. XpathWildCard(re, fn)
  926. X    char        *re;
  927. X    char        *fn;
  928. X{
  929. X    register int    c;
  930. X    register int    i;
  931. X    char        set[256];
  932. X    int        revset;
  933. X
  934. X    while ((c = *re++) != '\0') {
  935. X           if (c == '*') {
  936. X               if (*re == '\0') return 1; /* match anything at end */
  937. X               while (*fn != '\0') {
  938. X                  if (pathWildCard(re,fn)) return 1;
  939. X                  ++fn;
  940. X               }
  941. X               return 0;
  942. X           } else if (c == '?') {
  943. X               if (*fn++ == '\0') return 0;
  944. X           } else if (c == '[') {
  945. X               c = *re++;
  946. X               bzero(set,256);
  947. X               if (c == '!') {
  948. X                   revset=1;
  949. X                   c = *re++;
  950. X               } else {
  951. X                   revset=0;
  952. X               }
  953. X               while (c != ']') {
  954. X                  if (c == '\\') c = *re++;
  955. X                  set[c]=1;
  956. X                  if ((*re == '-') && (*(re+1) != ']')) {
  957. X                     re+=1;
  958. X                     while (++c <= *re) set[c]=1;
  959. X                     ++re;
  960. X                  }
  961. X                  c = *re++;
  962. X               }
  963. X               if (revset) for (i=1;i<256;++i) set[i] = ! set[i];
  964. X               if (! set[*fn++]) return 0;
  965. X           } else {
  966. X               if (c == '\\') c = *re++;
  967. X               if (c != *fn++) return 0;
  968. X           }
  969. X    }
  970. X    return(*fn == '\0');
  971. X}
  972. X
  973. X/* matchPaths implements the pid tool. This matches the *names* of files
  974. X * in the database against the input pattern rather than the *contents*
  975. X * of the files.
  976. X */
  977. Xint
  978. XmatchPaths(re, doit)
  979. X    char        *re;
  980. X    void        (*doit)();
  981. X{
  982. X    char *        absname;
  983. X    static char    *bitArray;
  984. X    struct idarg    *idArgs;
  985. X    register int    i;
  986. X    char        *reCompiled;
  987. X    int        count=0;
  988. X    int        matched;
  989. X
  990. X    if (pathRegExp) {
  991. X#ifdef REGEX
  992. X        if ((reCompiled = regcmp(re, 0)) == NULL) {
  993. X            fprintf(stderr, "%s: Syntax Error: %s\n", MyName, re);
  994. X            return 0;
  995. X        }
  996. X#endif
  997. X#ifdef RE_EXEC
  998. X        if ((reCompiled = re_comp(re)) != NULL) {
  999. X            fprintf(stderr, "%s: Syntax Error: %s (%s)\n", MyName, re, reCompiled);
  1000. X            return 0;
  1001. X        }
  1002. X#endif
  1003. X    }
  1004. X
  1005. X    if (bitArray == NULL) {
  1006. X        bitArray = malloc(BitArraySize);
  1007. X    }
  1008. X    bzero(bitArray, BitArraySize);
  1009. X
  1010. X    for (idArgs = IdArgs, i = 0; i < Idh.idh_pthc; i++, idArgs++) {
  1011. X        if (idArgs->ida_flags & IDA_BLANK) continue;
  1012. X        if (matchBase) {
  1013. X            absname = strrchr(idArgs->ida_arg, '/');
  1014. X            if (absname == NULL) {
  1015. X                absname = idArgs->ida_arg;
  1016. X            }
  1017. X        } else {
  1018. X            absname = spanPath(IdDir, idArgs->ida_arg);
  1019. X        }
  1020. X        if (pathRegExp) {
  1021. X#ifdef REGEX
  1022. X            matched = (regex(reCompiled, absname) != NULL);
  1023. X#endif
  1024. X#ifdef RE_EXEC
  1025. X            matched = (re_exec(absname));
  1026. X#endif
  1027. X        } else {
  1028. X            matched = pathWildCard(re, absname);
  1029. X        }
  1030. X        if (matched) {
  1031. X            BITSET(bitArray, i);
  1032. X            ++count;
  1033. X        }
  1034. X    }
  1035. X    if (count)
  1036. X        (*doit)(re, bitsToArgv(bitArray));
  1037. X    return count;
  1038. X}
  1039. END_OF_FILE
  1040. if test 20773 -ne `wc -c <'lid.c'`; then
  1041.     echo shar: \"'lid.c'\" unpacked with wrong size!
  1042. fi
  1043. # end of 'lid.c'
  1044. fi
  1045. echo shar: End of archive 6 \(of 7\).
  1046. cp /dev/null ark6isdone
  1047. MISSING=""
  1048. for I in 1 2 3 4 5 6 7 ; do
  1049.     if test ! -f ark${I}isdone ; then
  1050.     MISSING="${MISSING} ${I}"
  1051.     fi
  1052. done
  1053. if test "${MISSING}" = "" ; then
  1054.     echo You have unpacked all 7 archives.
  1055.     rm -f ark[1-9]isdone
  1056. else
  1057.     echo You still need to unpack the following archives:
  1058.     echo "        " ${MISSING}
  1059. fi
  1060. ##  End of shell archive.
  1061. exit 0
  1062.  
  1063. exit 0 # Just in case...
  1064.